/******************************************************************************
 * \brief	缓存队列（先进先出的缓存）的实现
 * \details	可以用作系统缓存、各个模块间的数据缓冲、通信链路的数据缓冲
 *			队列的静态分配需在上层模块中实现；
 *			静态初始化时，同个缓存队列内的每个缓存大小一样
 * \note	File format: UTF-8，中文编码：UTF-8
 * \author	将狼才鲸
 * \date	2023-03-08
 ******************************************************************************/

#ifndef _QUEUE_BUFFER_H_
#define _QUEUE_BUFFER_H_

/*********************************** 头文件 ***********************************/
#include "queue.h"
#include <stdint.h>	/* uint32_t... */

/*********************************** 宏定义 ***********************************/
#define QBUF_MARK		0xAABBCCDD	/* 魔术字，用于判断队列内容是否合法 */
#define QBUF_ISVALID(x)	((x) && ((x)->mark == QBUF_MARK))

/* 当前缓存携带的参数 */
#define SYS_BUF_FLAG_MARK	(0x000000FF)
#define SYS_BUF_FLAG_SOF	(0x00000001)	/* 文件开始 */
#define SYS_BUF_FLAG_EOF	(0x00000002)	/* 文件结束 */
/* 顺延的值为0x00000004 0x00000008 0x00000010 0x00000020... */

/********************************** 类型定义 **********************************/
/**
 * \brief	缓存的来源
 */
enum {
	QBUF_TYPE_MALLOC,	/* 使用malloc为每个缓存动态分配空间 */
	QBUF_TYPE_ARRAY		/* 初始化时使用静态数组为所有缓存一次性分配空间 */
};

/**
 * \brief	系统缓存的分类
 */
enum {
	/* 已释放的缓存；静态分配空间的情况下，以下各队列的元素释放后都放回到此处 */
	QBUF_GROUP_FREE,

	QBUF_GROUP_DATBUF,	/* 数据缓存 */
	QBUF_GROUP_MSGBUF,	/* 消息缓存 */
	QBUF_GROUP_TMPBUF,	/* 临时缓存，用完即退回 */
	QBUF_GROUP_COUNT	/* 缓存分类的组别数 */
};

/**
 * \brief	静态初始化所有缓存时的参数
 */
typedef struct _qbuf_group_cfg {
	uint32_t type;		/* QBUF_TYPE_ARRAY... */
	uint32_t count;		/* 该组内缓存总个数 */
	uint32_t unitsize;	/* 每个缓存元素的最大容量 */
	char *addr;			/* 整块缓存的起始地址 */
} qbuf_group_cfg_t;

/**
 * \brief	单个缓存
 */
typedef struct _qbuf {
	queue_t queue;	/* 队列节点 */
	uint32_t mark;	/* 用魔术字标识该缓存是否正常 */
	uint32_t flags;	/* 标识该缓存的类型，如文件结尾 */
	uint32_t group;	/* 属于哪个缓存队列（一个缓存可以移动到别的队列） */
	char *addr;		/* 当前缓存的地址 */
	uint32_t size;	/* 缓存总大小 */
	uint32_t offset;/* 有效数据的起始位置 */
	uint32_t len;	/* 有效数据的长度 */
	uint32_t id;	/* 缓存的序号 */
	uint64_t user;	/* 私有数据，做拓展用 */
} qbuf_t;

/********************************** 接口函数 **********************************/
/**
 * \brief	将几个系统缓存队列中的所有缓存节点都推到已释放队列中
 * \details 等待各个系统缓存队列的进一步初始化，以及内存分配的操作
 */
extern void qbuf_init(void);

/**
 * \brief	静态初始化一个缓存队列，分配好队列内所有的缓存
 * \param	qg:	该队列的静态初始化配置参数
 * \param	queue_entry:	该队列的类型，如QBUF_GROUP_DATBUF
 */
extern int qbuf_group_cfg(qbuf_group_cfg_t *qg, uint32_t group);

/**
 * \brief   从指定队列内获取一个空的缓存
 * \details 同时会初始化这个缓存，这个缓存在用完后要记得释放回去
 * \param   group:  QBUF_GROUP_DATBUF等缓存队列的名称
 */
extern qbuf_t *qbuf_alloc(uint32_t group);

/**
 * \brief	缓存用完后要进行释放
 * \details	释放回该队列的已释放链表中
 */
extern int qbuf_free(qbuf_t *buf);

/**
 * \brief	将一个缓存发送到该缓存所属的队列中
 */
extern int qbuf_put(qbuf_t *buf);

/**
 * \brief	从一个队列中获取一个含有有效数据的缓存
 */
extern qbuf_t *qbuf_get(uint32_t group);

#endif /* _QUEUE_BUFFER_H_ */

/*********************************** 文件尾 ***********************************/
